home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part2 / 15490 < prev    next >
Encoding:
Text File  |  1996-08-05  |  3.8 KB  |  108 lines

  1. Path: news.compuserve.com!newsmaster
  2. From: Philippe Verdy <100105.3120@compuserve.com>
  3. Newsgroups: comp.lang.c++
  4. Subject: Re: casting a void pointer back to a function pointer
  5. Date: 5 Apr 1996 21:34:19 GMT
  6. Organization: CompuServe Incorporated
  7. Message-ID: <4k43kr$2ap@dub-news-svc-3.compuserve.com>
  8. NNTP-Posting-Host: hd41-018.compuserve.com
  9.  
  10. What you want to do is not portable, because code pointers
  11. and data pointers may be stored differently (mainly on DOS
  12. platforms, in compact and medium memory models). In order
  13. to safely typecast a function pointer to a data pointer, you'll
  14. need additional pointer model specifiers.
  15. However, assuming the memory model you are using is not
  16. concerned (using small, large, huge, and the common flat
  17. memory models), you can do the following :
  18.  
  19. dlabell@pcs.cnu.edu (Daniel LaBell) wrote :
  20. > I'm going to skip explaining why I want to do this, and get right to the
  21. > problem.  How do I cast a pointer to a function pointer?
  22. > Here is trivial example that shows the problem.
  23. > void foo1(){  cout << " foo1 " << endl; }
  24. > void foo2(){  cout << " foo2 " << endl; }
  25. > void foo3( int x )
  26. > { cout << " foo3, argument = " << x << endl; }
  27. > void do_a_foo( void (*fun)() )
  28. > {  (*fun)(); }
  29. > void do_a_foo2( int x,  void (*fun) (int ) )
  30. > {  (*fun) ( x ); } 
  31. > int main()
  32. > {
  33. >   do_a_foo  ( foo1 );
  34. >   do_a_foo  ( foo2 );
  35. >   do_a_foo2 ( 2, foo3 );
  36.  
  37. Here is the danger (warnings: segment lost in conversion, etc...)
  38. >   void * x=foo2;
  39. You should declare a large enough data pointer type under DOS
  40. using the _far keyword, embedded in a FAR macro used for porting
  41. reasons (if you need to compile for DOS):
  42. #ifndef FAR
  43. #  if defined(MSDOS) || defined(WINDOWS) && !defined(WIN32)
  44. #    define FAR _far
  45. #  else
  46. #    define FAR //nothing
  47. #  endif
  48. #endif
  49. ...
  50. void FAR* x = (void FAR*)foo2;
  51.  
  52. The solution to your problem :
  53. >   do_a_foo  (x); // I don't know the syntax to do this cast. :(
  54. is then:
  55.   do_a_foo( (void (*)()) x );
  56. which uses a function pointer typecast. Here the typecast means
  57. it is a pointer to a function taking no parameter, and returning
  58. void... Such typecast is really dangerous, because using it on
  59. undetermined pointers will may be completely hang the system
  60. or corrupt your current process under Unix. No type-checking
  61. also occurs on parameters and on the returned type, so the
  62. called function may fail within its execution, or the calling
  63. function may hang at return time !!!
  64.  
  65. You'll only need it when you have to pass a generic client
  66. pointer (of type void*) as an argument to an API function
  67. which enables you to return to your code thru a specified
  68. callback.
  69.  
  70. But I would advise you to prefereably create a structure
  71. containing the function pointer, declared like this :
  72. struct parameter {
  73.   void (*pf)();
  74. };
  75. then safely assign parameter::pf with x;
  76. finally call your API using a reference or pointer to your
  77. parameter structure.
  78. When you get this pointer (say parameter *p), you can call
  79. back the assigned function like this:
  80.   (*p->pf) ();
  81. or simply:
  82.   p->pf ();
  83. Hope this will help...
  84.  
  85. >   return 0;
  86. > }
  87. > I get this warning message from g++:
  88. > :/home/student/dlabell/C/test.cc: In function `int main()':
  89. > :/home/student/dlabell/C/test.cc:21: warning: ANSI C++ forbids implicit conversion from `void *' in argument passing
  90. > :
  91. > :Compilation finished at Thu Apr  4 01:18:20
  92. > So, now my program isn't portable, and if I overload do_a_foo instead of
  93. > making do_a_foo2, it wouldn't compile at all.  So, I need to know the syntax
  94. > for casting a pointer to a pointer to a function.  Can this be done in a
  95. > portable way? ( how about for ANSI C? ) If not, can this be done in
  96. > g++/gcc? And also if it isnt ANSI wouldn't that violate the premise that
  97. > "any pointer can be cast to void * and back again without loss of
  98. > information"?  Or can I declare a type of pointer to a function?
  99. >  
  100. > --
  101. > Daniel LaBell
  102.  
  103.